﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using Helpers.Extensions;
using Helpers;

namespace HttpRequester
{
    public class RequestChainContext
    {
        public ProxyInfo Proxy { get; set; }
        public Dictionary<string, Cookie> InputCookies { get; set; }
        public Dictionary<string, string> CommonCustomHeaders { get; set; }
        public Dictionary<HttpRequestHeader, string> CommonWellknownHeaders { get; set; }
        public string PreviousResponseContent { get; set; }

        //public static T Create<T>()
        //    where T : RequestChainContext //, new()
        //{
        //    return new T();
        //}

        public RequestChainContext()
        {
            Clear();
        }

        public RequestChainContext(RequestChainContext context)
            : this()
        {
            if (context != null)
                Copy(context);
        }

        public virtual void Clear()
        {
            InputCookies = new Dictionary<string, Cookie>();
            CommonCustomHeaders = new Dictionary<string, string>();
            CommonWellknownHeaders = new Dictionary<HttpRequestHeader, string>();
        }


        public virtual void Copy(RequestChainContext context)
        {
            #warning  Null validation can be removed
            if (context.Proxy != null)
            {
                Proxy = new ProxyInfo(context.Proxy.ProxyUrl
                    , context.Proxy.ProxyCredentials.UserName, context.Proxy.ProxyCredentials.Password);
            }
            else
                Proxy = null;
            
            context.InputCookies.Keys.ToList().ForEach(
                key => InputCookies.AddOrReset(key, context.InputCookies[key]));

            context.CommonCustomHeaders.Keys.ToList().ForEach(
                key => CommonCustomHeaders.AddOrReset(key, context.CommonCustomHeaders[key]));

            context.CommonWellknownHeaders.Keys.ToList().ForEach(
                key => CommonWellknownHeaders.AddOrReset(key, context.CommonWellknownHeaders[key]));

            PreviousResponseContent = context.PreviousResponseContent;
        }

        public void AddCustomHeader(string name, string value)
        {
            value = value ?? string.Empty;
            CommonCustomHeaders.AddOrReset(name, value);
        }

        public void AddCustomHeader(string header)
        {
            if (StringHelper.IsnullOrBlank(header))
                return;

            string[] headerParts = header.Split(':');
            if (headerParts.Length > 1)
            {
                string headerName = headerParts[0].Trim();
                string headerValue = headerParts[1].Trim();
                CommonCustomHeaders.AddOrReset(headerName, headerValue);
            }
            else
            {
                CommonCustomHeaders.AddOrReset(header, null);
            }
        }

        public void LoadHeaders(Dictionary<string, string> customHeaders
            , Dictionary<HttpRequestHeader, string> wellknownHeaders)
        {
            if (!CollectionHelper.IsNullOrEmpty(customHeaders))
                customHeaders.Keys.ToList()
                    .ForEach(name => AddCustomHeader(name, customHeaders[name]));

            if (!CollectionHelper.IsNullOrEmpty(wellknownHeaders))
                wellknownHeaders.Keys.ToList()
                    .ForEach(name => AddWellknownHeaders(name, wellknownHeaders[name]));
        }

        public void AddWellknownHeaders(HttpRequestHeader key, string value)
        {
            CommonWellknownHeaders.AddOrReset(key, value);
        }

        public void LoadInputCookies(List<Cookie> source)
        {
            if (InputCookies == null)
                InputCookies = new Dictionary<string, Cookie>();

            if (CollectionHelper.IsNullOrEmpty(source))
                return;

            source.ForEach(c => InputCookies.AddOrReset(c.Name, c));
        }

        public void AddCookie(Cookie c)
        {
            if (c == null) return;
            InputCookies.AddOrReset(c.Name, c);
        }
    }
}
